package Prototype;

import Model.Main.Worksheet;
import java.lang.String.*;
import Model.Inputs.*;
import Model.Gates.*;
import Model.Main.Wire;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.*;

/**
 *
 ** @author citromos ezustfoka
 */
public class ProtoController {

    private static final Logger logger =
            Logger.getLogger(ProtoController.class.getName());
    private Worksheet sheet;
    private Boolean running;
    private ConInt console;
    private HashMap<String, Object> namebase;

    public ProtoController() {
        logger.finest("ProtoControl created!");
        namebase = new HashMap<String, Object>();
        sheet = new Worksheet();
        console = new ConInt(ProtoController.this);
        console.interpreter();
    }

    public void addNameBase(String name, Object o) {
        try {
            namebase.put(name, o);


        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }

    public Object getObjectfromNameBase(String name) {
        if (namebase.get(name) != null) {
            return namebase.get(name);
        }
        return ("undefined");

    }

    public int nameIsInvalid(String name) {
        if (namebase.get(name) == null) {
            return 1;
        }
        return 0;

    }

    public void delObjectfromNameBase(String name) {
        if (namebase.get(name) != null) {
            return;
        }
        namebase.remove(name);

    }

    /**
     *
     * Futtatás indítása
     * 
     */
    public void start() {
        running = true;
        while (running) {
            runOnce();
        }
    }

    public void clear() {
        sheet.clear();
    }

    /**
     *
     * Futtatás leállítás, az értékek alaphelyzetbe állnak.
     */
    public void stop() {
        running = false;
        clear();

    }

    /**
     *
     *  Futtatás megállítása, minden úgy marad, ahogy a megállítás pillanatában volt.
     */
    public void pause() {
        running = false;
    }

    /*
     *
     * Egy kör szimulációt futtat.
     */
    public void runOnce() {
        logger.finest("Starting runOnce simulation!");
        try {
            sheet.runInputsOnce();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

    /**
     * A worksheet osztály setState függvényét hívja meg.
     * @param onInput : Az az Input példány referenciája, aminek az értékét szeretnénk beállítani.  
     * @param state :  A bemenet értéke
     */
    public void setState(Input onInput, Boolean state) {
        logger.log(Level.FINEST, "Call for set state state " + state + " on " + onInput + "");
        sheet.setState(onInput, state);
    }

    /**
     *A Worksheet osztály ugyanilyen paraméterekkel rendelkező addWire függvényét hívja meg.
     * @param from Az Input aminek a kimenetére állítjuk a wire-t
     * @param to A Gate aminek a bemenetére állítjuk a wire-t
     * @return
     */
    public void addWire(Input from, Gate to, int toInput, String name) {
        logger.log(Level.FINEST, "Call for add wire between " + from + " and " + to + " on input " + toInput + ".");
        try {
            sheet.addWire(from, to, toInput, name);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

    /**
     * A Worksheet osztály ugyanilyen paraméterekkel rendelkező addWire függvényét hívja meg.
     * @param from  A Gate aminek a kimenetére állítjuk a wire-t
     * @param to A Gate aminek a bemenetére állítjuk a wire-t
     * @return
     */
    public void addWire(Gate from, int fromOutput, Gate to, int toInput, String name) {
        logger.log(Level.FINEST, "Call for add wire between " + from + " and " + to + " on input " + toInput + ".");
        try {
            sheet.addWire(from, fromOutput, to, toInput, name);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

    /**
     *Kölyök Wire
     *
     * @param from Wire amire rá lesz kötve a wire
     * @param to a Gate amire rá akarjuk kötni
     * @param toInput A Gate bemenetének száma
     * @param name a Wire neve
     * @return
     * 
     */
    public void addchildWire(Wire child, Wire from, Gate to, int toInput, String name) throws Exception {
        sheet.addchildWire(child, from, to, toInput, name);
    }

    /**
     *A Worksheet osztály ugyanilyen paraméterekkel rendelkező delWire függvényét hívja meg.
     * @param from  Az Input aminek a kimenetéről töröljük a wire-t
     * @param to A Gate aminek a bemenetéről töröljük a wire-t
     * @return
     */
    public void delWire(Input from, Gate to) {
        throw new UnsupportedOperationException();
    }

    /**
     *A Worksheet osztály ugyanilyen paraméterekkel rendelkező delWire függvényét hívja meg.
     * @param from  A Gate aminek a kimenetéről töröljük a wire-t
     * @param to A Gate aminek a bemenetéről töröljük a wire-t
     * @return
     */
    public void delWire(Gate from, Gate to) {
        throw new UnsupportedOperationException();
    }

    /**
     * Gate hozzáadása
     * A worksheet ugyanilyen paraméterekkel rendelkező addGate függvényét hívja meg.
     * @param g A hozzáadni kívánt Gate.
     * @return
     * 
     * 
     */
    public void addGate(Gate g) {
        logger.log(Level.FINEST, "Call for add " + g + " to worksheet.");
        sheet.addGate(g);
    }

    /**
     * Adott Gates példány megadása a Gates Array listből.
     * @param n n. elemet adja vissza a Gates Array listből
     * @return
     *
     */
    public void getGate(int n) {
        throw new UnsupportedOperationException();
    }

    /**
     * Adott Gates példány megadása a Gates Array listből.
     * @param gate inp ezen elem értékének visszaadása a logba
     * @return
     *
     */
    public void getVal(Gate gate) {
        logger.log(Level.FINE, "" + gate.getClass().getName() + " " + gate.getName() + "'s value is: " + gate.getVal() + "");
    }

    /**
     * Inpu értékének visszaadása
     * @param inp ezen elem értékének visszaadása a logba
     * @return
     *
     */
    public void getVal(Input inp) {
        logger.log(Level.FINE, "" + inp.getClass().getName() + " " + inp.getName() + "'s value is: " + inp.getVal() + "");
    }

    /**
     * Input hozzáadása.
     * A worksheet ugyanilyen paraméterekkel rendelkező addInpit függvényét hívja meg.
     * @param i Az input amit a hozzá akarunk adni.
     * @return
     * 
     */
    public void addInput(Input i) {
        logger.log(Level.FINEST, "Call for add " + i + "i to worksheet.");
        sheet.addInput(i);
    }

    public void addGateComposite(Composite c, Gate g) {
        sheet.addGateComposite(c, g);

    }

    /**
     * A worksheet addwire függvényét hívja meg.
     * A kompozit bemenetét köti össze egy belső kapu bemenetével.
     * @param fromInput
     * @param to
     * @param inputNumber
     */
    public void addWire(Composite comp, int fromInput, Gate to, int inputNumber, String name) throws Exception {
        sheet.addWire(comp, fromInput, to, inputNumber, name);
    }

    /**
     * A kompozit addwire függvényét hívja meg.
     * Egy belső kapu kimenetét köti össze a kompozit kimenetével.
     * @param from
     * @param outputNumber
     * @param toInput
     */
    public void addWire(Composite comp, Gate from, int outputNumber, int toOutput, String name) throws Exception {
        sheet.addWire(comp, from, outputNumber, toOutput, name);
    }

    /**
     * Gate törlése
     * @param g    
     */
    public void delGate(Gate g) throws Exception {
        sheet.delGate(g);
    }

    /**
     * Input törlése
     * 
     * @param i    
     */
    public void delInput(Input i) throws Exception {
        sheet.delInput(i);
    }

    /**
     *Inputs és Gates osztályt összekötő vezeték törlése.
     *
     * @param from az Input, amiről ki van kötve a wire
     * @param name a Wire neve
     * @return
     * 
     */
    public void delWire(Input from, String name) throws Exception {
        sheet.delWire(from, name);

    }

    /**
     *Gates és Gates osztályt összekötő vezeték törlése.
     * @param from  A Gate aminek a kimenetéről töröljük a wire-t
     * @param fromOutput a Gate melyik (int) outputjáról töröljük a wire-t
     * @param name a wire neve (ellenőrzés céljából)
     * @return
     * 
     */
    public void delWire(Gate from, int fromOutput, String name) throws Exception {
        sheet.delWire(from, fromOutput, name);
    }
}
